home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- *
- * OSLClassDocument.c
- *
- * OSL support for the cDocument Apple Event Registry object
- *
- ****************************************************************************/
-
- #include <stdio.h> // for sprintf()
-
- #include "OSLClassDocument.h"
-
- #include "AERCoreSuite.h"
- #include "AppleEvent.h"
- #include "OSLHelpers.h"
-
- #include "Documents.h"
- #include "DocumentADT.h"
- #include "DocumentHelpers.h"
-
- #include "ElementADT.h"
- #include "ElementHelpers.h"
-
- #include "Assertion.h"
- #include "Sounds.h"
- #include "StringUtils.h" // for PToCString(). etc.
-
- // ----------------------------------------------------------------------------
- // Core Suite Object Event handlers
- // ----------------------------------------------------------------------------
-
- static OSErr HandleClose (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
- static OSErr HandleCount (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
- static OSErr HandleDataSize (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
- static OSErr HandleDelete (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
- static OSErr HandleDuplicate (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
- static OSErr HandleExists (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
- static OSErr HandleGetData (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
- static OSErr HandleMake (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
- static OSErr HandleMove (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
- static OSErr HandleOpen (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
- static OSErr HandlePrint (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
- static OSErr HandleQuit (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
- static OSErr HandleSave (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
- static OSErr HandleSetData (AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply);
-
- // ----------------------------------------------------------------------------
- // Do the application-specific part of the work
-
- static OSErr DoClose (AEDesc *token, const AEDesc *saving, AEDesc *savingIn);
- static OSErr DoSave (AEDesc *token, const AEDesc *inFile, AEDesc *asType);
-
- // ----------------------------------------------------------------------------
- // Core Suite Object Accessor functions
- // ----------------------------------------------------------------------------
-
- static OSErr
- MakeNewObject(
- const DescType objectToCreate,
- const DescType insertionPosition,
- const AEDesc *token,
- const AEDesc *ptrToWithData,
- const AEDesc *ptrToWithProperties,
- AppleEvent *reply);
-
- static pascal OSErr
- DocumentFromApplicationAccessor(
- DescType desiredClass,
- const AEDesc* containerToken,
- DescType containerClass,
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken,
- long refCon);
-
- static OSErr
- PropertyFromListAccessor(
- DescType desiredClass,
- const AEDesc* containerToken,
- DescType containerClass,
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken,
- long refCon);
-
- static OSErr
- PropertyFromObjectAccessor(
- DescType desiredClass,
- const AEDesc* containerToken,
- DescType containerClass,
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken,
- long refCon);
-
- static OSErr GetDataFromList (AEDesc *srcList, AEDesc *desiredTypes, AEDesc *dstList);
- static OSErr GetDataFromObject (AEDesc *token, AEDesc *desiredTypes, AEDesc *data);
-
- static OSErr SetDataForList (AEDesc *token, AEDesc *data);
- static OSErr SetDataForObject (AEDesc *token, AEDesc *data);
-
- static Boolean CanGetProperty (DescType property);
- static Boolean CanSetProperty (DescType property);
- static OSErr SetProperties (DocumentReference document, AEDesc *propertyRecord);
-
- static OSErr ProcessFormRelativePostition (const AEDesc* anchorToken, const AEDesc *keyData, DocumentReference *document);
-
- static long GetDocumentIndex (DocumentReference document);
-
- /*****************************************************************************
- *
- * DocumentEventDispatcher
- *
- * Handles all OSL messages that cDocument should handle
- *
- *****************************************************************************/
-
- OSErr
- DocumentEventDispatcher(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply, long refcon)
- {
- #pragma unused (refcon)
-
- OSErr error = noErr;
-
- AEEventID eventID;
- OSType typeCode;
- Size actualSize = 0L;
-
- // Get the event ID
-
- error = AEGetAttributePtr(appleEvent,
- keyEventIDAttr,
- typeType,
- &typeCode,
- (Ptr)&eventID,
- sizeof(eventID),
- &actualSize);
-
- if (error != noErr) {
- return error;
- }
-
- switch (eventID) {
-
- case kAEClone:
- error = HandleDuplicate(token, appleEvent, reply);
- break;
-
- case kAEClose:
- error = HandleClose(token, appleEvent, reply);
- break;
-
- case kAECountElements:
- error = HandleCount(token, appleEvent, reply);
- break;
-
- case kAECreateElement:
- error = HandleMake(token, appleEvent, reply);
- break;
-
- case kAEDelete:
- error = HandleDelete(token, appleEvent, reply);
- break;
-
- case kAEDoObjectsExist:
- error = HandleExists(token, appleEvent, reply);
- break;
-
- case kAEGetData:
- error = HandleGetData(token, appleEvent, reply);
- break;
-
- case kAEGetDataSize:
- error = HandleDataSize(token, appleEvent, reply);
- break;
-
- case kAEMove:
- error = HandleMove(token, appleEvent, reply);
- break;
-
- case kAEOpen:
- error = HandleOpen(token, appleEvent, reply);
- break;
-
- case kAEPrint:
- error = HandlePrint(token, appleEvent, reply);
- break;
-
- case kAEQuitApplication:
- error = HandleQuit(token, appleEvent, reply);
- break;
-
- case kAESave:
- error = HandleSave(token, appleEvent, reply);
- break;
-
- case kAESetData:
- error = HandleSetData(token, appleEvent, reply);
- break;
-
- default:
- error = errAEEventNotHandled;
- break;
- }
-
- if (error != noErr && reply->descriptorType != typeNull)
- PutReplyErrorNumber(reply, error);
-
- return error;
- }
-
- #pragma mark -
- // ----------------------------------------------------------------------------
- // Core Suite Object Event handlers
- // ----------------------------------------------------------------------------
- // "close <DocRef> saving <yes|no|ask> saving in <FileRef>"
-
- static OSErr
- HandleClose(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
- {
- #pragma unused (reply)
-
- OSErr error = noErr;
-
- DescType typeCode = 0L;
-
- AEDesc saving = {typeNull, nil};
- AEDesc savingIn = {typeNull, nil};
-
- AEDesc *ptrToSaving = NULL;
- AEDesc *ptrToSavingIn = NULL;
-
- // Extract the [saving yes/no/ask] optional parameter, if present
-
- error = AEGetParamDesc(appleEvent, keyAESaveOptions, typeWildCard, &saving);
-
- if (error == noErr)
- ptrToSaving = &saving;
- else if (error == errAEDescNotFound)
- error = noErr;
- else
- goto Cleanup;
-
- // Extract the [saving in <alias>] optional parameter, if present
-
- error = AEGetParamDesc(appleEvent, keyAEFile, typeFSS, &savingIn);
-
- if (error == noErr)
- ptrToSavingIn = &savingIn;
- else if (error == errAEDescNotFound)
- error = noErr;
- else
- goto Cleanup;
-
- // Check for any required parameters we may have missed
-
- error = CheckForUnusedParameters(appleEvent);
- if (error != noErr)
- goto Cleanup;
-
- // Now, do the application-related work
-
- // Now, close one or more items
-
- if (TokenContainsTokenList(token))
- {
- AEDescList flatList = {typeNull, nil};
- AEDesc singleToken = {typeNull, nil};
- long numItems;
- long itemNum;
- AEKeyword keyword;
-
- error = AECreateList(NULL, 0L, false, &flatList);
- if (error == noErr)
- error = FlattenAEList(token, &flatList);
-
- if (error == noErr)
- {
- error = AECountItems(&flatList, &numItems);
- if (error == noErr || numItems > 0)
- {
- for (itemNum = 1; itemNum <= numItems; itemNum++)
- {
- error = AEGetNthDesc(&flatList, itemNum, typeWildCard, &keyword, &singleToken);
-
- if (error == noErr)
- error = DoClose(&singleToken, ptrToSaving, ptrToSavingIn);
- else
- break;
-
- AEDisposeDesc(&singleToken);
- }
- }
- }
-
- AEDisposeDesc(&flatList);
- AEDisposeDesc(&singleToken);
- }
- else
- {
- error = DoClose(token, ptrToSaving, ptrToSavingIn);
- }
-
- Cleanup:
-
- AEDisposeDesc(&saving);
- AEDisposeDesc(&savingIn);
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
- // This is called to count the various things contained inside a document object
- // Eg., "count rectangles in document 1"
- // OR, if we receive a list of document, we could be counting documents
- // that satisfy a whose statement
-
- static OSErr
- HandleCount(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
- {
- OSErr error = noErr;
- long numberOfObjects = 0L;
- DescType objectClass;
- DocumentReference document = nil;
-
- // Get the class of object that we will count
-
- error = GetObjectClassFromAppleEvent(appleEvent, &objectClass);
-
- // Make sure we got & handled all of the required parameters
-
- if (error == noErr)
- error = CheckForUnusedParameters(appleEvent);
-
- // If we receive a list, then we're counting documents via a whose clause
-
- if (TokenContainsTokenList(token))
- {
- AEDesc tempToken = {typeNull, nil};
-
- error = GetFirstNonListToken(token, &tempToken);
-
- if (error == noErr && tempToken.descriptorType == cDocument)
- error = AECountItems(token, &numberOfObjects);
-
- AEDisposeDesc(&tempToken);
- }
- else
- {
- if (error == noErr)
- error = GetDocumentReferenceFromToken(token, &document);
-
- if (error == noErr)
- {
- switch (objectClass)
- {
- default:
- numberOfObjects = CountElementsByClass(GetDocumentElementList(document), objectClass);
- break;
- }
- }
- }
-
- // Now return the result in the reply apple event
-
- if (error == noErr && reply != NULL && reply->descriptorType != typeNull)
- {
- error = AEPutParamPtr(reply, keyAEResult, typeLongInteger, (Ptr)&numberOfObjects, sizeof(long));
- }
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
- // This is called to get the size of the data for an object in a document
-
- static OSErr
- HandleDataSize(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
- {
- OSErr error = noErr;
- AEDesc data = {typeNull, nil};
- long size = 0L;
-
- // First, get the data
- error = HandleGetData(token, appleEvent, reply);
-
- // now, extract it from the reply
-
- if (error == noErr)
- error = AEGetKeyDesc(reply, keyDirectObject, typeWildCard, &data);
-
- if (error == noErr)
- {
- if (data.dataHandle != nil)
- {
- size = GetHandleSize(data.dataHandle);
- }
- error = AEPutParamPtr(reply,
- keyAEResult,
- typeLongInteger,
- (Ptr)&size,
- sizeof(long));
- }
-
- AEDisposeDesc(&data);
-
- return error;
-
- }
-
- // ----------------------------------------------------------------------------
- // "Delete document" is treated as equivalent to "close document"
-
- static OSErr
- HandleDelete(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
- {
- OSErr error = HandleClose(token, appleEvent, reply);
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
- // Handles messages like "duplicate document 1"
- // ••• should handle the the options [to location referece] parameter also •••
-
- static OSErr
- HandleDuplicate(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
- {
- #pragma unused (token, appleEvent, reply)
-
- return errAEEventNotHandled;
- }
-
- // ----------------------------------------------------------------------------
- // If document 1 exists...
- // The AEResolve() function in AERCoreSuite.c will already have filtered
- // out all cases where the object did not exist, so this function should
- // always return TRUE.
-
- static OSErr
- HandleExists(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
- {
- #pragma unused (token, appleEvent)
-
- OSErr error = noErr;
- Boolean foundIt = true;
-
- if (error == noErr && reply != NULL && reply->descriptorType != typeNull)
- {
- error = AEPutParamPtr(reply,
- keyAEResult,
- typeBoolean,
- (Ptr)&foundIt,
- sizeof(Boolean));
- }
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
-
- static OSErr
- HandleGetData(AEDesc *tokenOrTokenList, const AppleEvent *appleEvent, AppleEvent *reply)
- {
- OSErr error = noErr;
- AEDesc data = {typeNull, nil};
- AEDesc desiredTypes = {typeNull, nil};
-
- AEGetParamDesc(appleEvent, keyAERequestedType, typeAEList, &desiredTypes);
-
- error = GetDataFromDocument(tokenOrTokenList, &desiredTypes, &data);
-
- if (error == noErr && reply->descriptorType != typeNull)
- error = AEPutKeyDesc(reply, keyDirectObject, &data);
-
- AEDisposeDesc(&data);
- AEDisposeDesc(&desiredTypes);
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
- // Make a new document
-
- static OSErr
- HandleMake(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
- {
- OSErr error = noErr;
-
- OSType typeCode;
- Size actualSize;
-
- DescType newObjClass = typeNull;
- DescType insertionPos = typeNull;
-
- AEDesc insertionLoc = {typeNull, nil};
- AEDesc objectSpec = {typeNull, nil};
-
- long documentNumber = 0L;
-
- DocumentReference document = nil;
-
- // Optional parameters
- AEDesc withData = {typeNull, nil};
- AEDesc withProperties = {typeNull, nil};
-
- AEDesc *ptrToWithData = NULL;
- AEDesc *ptrToWithProperties = NULL;
-
- newObjClass = **(DescType**)(token->dataHandle);
-
-
- // For Create Element, the object specifier is contained in
- // a typeInsertionLoc record instead of in a direct parameter.
- // We coerce the insertionLoc record into an AERecord so we can extract the fields.
- // Notice that this is a REQUIRED parameter, but we give it a default behavior
- // by creating a new document as the frontmost document
-
- error = AEGetParamDesc(appleEvent, // Extract as a AERecord
- keyAEInsertHere,
- typeAERecord,
- &insertionLoc);
-
- if (error == errAEDescNotFound)
- {
- insertionPos = kAEBeginning;
- error = noErr;
- }
- else if (error == noErr)
- {
-
- // Get the enumerated insertion location (at end, in front, before, after, replace.)
-
- error = AEGetKeyPtr(&insertionLoc,
- keyAEPosition, // insertion location
- typeEnumeration,
- &typeCode,
- (Ptr)&insertionPos,
- sizeof(insertionPos),
- &actualSize);
-
- // Extract and resolve the object specifier from the insertion location record.
- // In a case like "make new document before document 2",
- // the ospec will resolve to "document 2"
-
- error = AEGetKeyDesc(&insertionLoc,
- keyAEObject,
- typeWildCard,
- &objectSpec);
- }
-
- // if there was a object specifier in the insertion location (eg, "before document 1",
- // then we call AEResolve() to get a token for it,
- // Otherwise, is was something like "at end" or "at beginning", which is also OK,
- // then deal with it correctly later.
-
- if (objectSpec.descriptorType == typeNull)
- {
- AEDisposeDesc(token); // destroy it's old representation, toke will no be null descriptor
- }
- else
- {
- error = AEResolve(&objectSpec,
- kAEIDoMinimum,
- token); // token will contain info about the object to insert before, after, etc.
- if (error != noErr)
- {
- goto CleanUp;
- }
- }
-
- // Extract the optional parameters from the AppleEvent
-
- // ----- [with data ....] -----
-
- error = AEGetParamDesc(appleEvent,
- keyAEData,
- typeWildCard,
- &withData);
- if (error != noErr && error != errAEDescNotFound)
- goto CleanUp;
-
- if (error == errAEDescNotFound)
- error = noErr;
- else
- ptrToWithData = &withData;
-
- // ----- [with properties {property: value, ...}] -----
-
- error = AEGetParamDesc(appleEvent,
- keyAEPropData,
- typeWildCard,
- &withProperties);
- if (error != noErr && error != errAEDescNotFound)
- goto CleanUp;
-
- if (error == errAEDescNotFound)
- error = noErr;
- else
- ptrToWithProperties = &withProperties;
-
- // Finally, use the token and other parameters to create & initialize the object
-
- if (error == noErr)
- {
- error = MakeNewObject(newObjClass, insertionPos, token, ptrToWithData, ptrToWithProperties, reply);
- }
-
- CleanUp:
-
- AEDisposeDesc(&insertionLoc);
- AEDisposeDesc(&objectSpec);
- AEDisposeDesc(&withData);
- AEDisposeDesc(&withProperties);
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
-
- static OSErr
- HandleMove(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
- {
- #pragma unused (token, appleEvent, reply)
-
- OSErr error = errAEEventNotHandled;
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
- // class cDocument always refers to an OPEN document - so this handler would
- // not seem to be needed here
-
- static OSErr
- HandleOpen(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
- {
- #pragma unused (token, appleEvent, reply)
-
- OSErr error = errAEEventNotHandled;
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
-
- static OSErr
- HandlePrint(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
- {
- #pragma unused (token, appleEvent, reply)
-
- OSErr error = errAEEventNotHandled;
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
-
- static OSErr
- HandleQuit(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
- {
- #pragma unused (token, appleEvent, reply)
-
- OSErr error = errAEEventNotHandled;
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
- // "save <DocRef> in <FileRef> as <FileTypeConstant>"
-
- static OSErr
- HandleSave(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
- {
- #pragma unused (reply)
-
- OSErr error = noErr;
-
- DescType typeCode = 0L;
-
- AEDesc inFile = {typeNull, nil};
- AEDesc asType = {typeNull, nil};
-
- AEDesc *ptrToInFile = NULL;
- AEDesc *ptrToAsType = NULL;
-
- // "The keyInteractLevelAttr attribute determines whether the
- // server app can interact with the user when handling the event"
-
- // error = AEGetAttributePtr(appleEvent, keyInteractLevelAttr, typeType, &);
-
-
- // Extract the "in <FileRef>" optional parameter
-
- error = AEGetParamDesc(appleEvent, keyAEFile, typeFSS, &inFile);
-
- if (error == noErr)
- ptrToInFile = &inFile;
- else if (error == errAEDescNotFound)
- error = noErr;
- else
- goto Cleanup;
-
- // Extract the "as <FileType>" optional parameter
-
- error = AEGetParamDesc(appleEvent, keyAEFileType, typeType, &asType);
-
- if (error == noErr)
- ptrToAsType = &asType;
- else if (error == errAEDescNotFound)
- error = noErr;
- else
- goto Cleanup;
-
- // Check for any required parameters we may have missed
-
- error = CheckForUnusedParameters(appleEvent);
- if (error != noErr)
- goto Cleanup;
-
- // Now, do the application-related work
-
- error = DoSave(token, ptrToInFile, ptrToAsType);
-
- Cleanup:
-
- AEDisposeDesc(&inFile);
- AEDisposeDesc(&asType);
-
- return error;
- }
-
- // ----------------------------------------------------------------------------
-
- static OSErr
- HandleSetData(AEDesc *token, const AppleEvent *appleEvent, AppleEvent *reply)
- {
- #pragma unused (reply)
-
- OSErr error = noErr;
- AEDesc data = {typeNull, nil};
-
- DescType propertyCode;
- DescType objectClass;
-
- switch (token->descriptorType)
- {
- case typeAEList:
- error = ExtractKeyDataParameter(appleEvent, &data);
- if (error == noErr)
- error = SetDataForList(token, &data);
- break;
-
- case cProperty:
- propertyCode = ExtractPropertyCodeFromToken(token);
- objectClass = ExtractObjectClassFromToken(token);
- if (CanSetProperty(propertyCode))
- {
- error = ExtractKeyDataParameter(appleEvent, &data);
- if (error == noErr)
- error = SetDataForObject(token, &data);
- }
- else
- {
- error = errAENotModifiable;
- }
- break;
-
- default:
- error = errAENotModifiable;
- break;
- }
-
- AEDisposeDesc(&data);
-
- return error;
- }
-
-
-
- #pragma mark -
- // -----------------------------------------------------------------------------
- // Object Accessors
- //------------------------------------------------------------------------------
-
- OSErr
- InstallDocumentAccessors(void)
- {
-
- OSErr error;
-
- error = AEInstallObjectAccessor(cDocument,
- typeNull,
- NewOSLAccessorProc(DocumentFromApplicationAccessor),
- 0L,
- false);
-
- // although documents can't contain other documents,
- // we need this accessor to support formRelativePostion,
- // which sends us one document as a "container" and asks us to find
- // either the document before or after that document
-
- error = AEInstallObjectAccessor(cDocument,
- cDocument,
- NewOSLAccessorProc(DocumentFromApplicationAccessor),
- 0L,
- false);
-
- if (error == noErr)
- error = AEInstallObjectAccessor(cProperty,
- cDocument,
- NewOSLAccessorProc(PropertyFromDocumentAccessor),
- 0L,
- false);
-
- return error;
- }
-
- #pragma mark -
- //------------------------------------------------------------------------------
- // Retrieve the Document from the null container by the key form
-
- static pascal OSErr
- DocumentFromApplicationAccessor(
- DescType desiredClass, // cDocument
- const AEDesc* containerToken, // null container
- DescType containerClass, // cApplication
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken, // specified Document is returned in result
- long refCon)
- {
- #pragma unused (containerToken, containerClass, refCon)
-
- OSErr error = noErr;
- DocumentReference document = nil;
-
- DescType keyDataType = keyData->descriptorType;
-
- long index;
- long numItems;
- Boolean wantsAllItems = false;
-
- AEDesc startObject = {typeNull, nil}; // These are used to resolve formRange
- AEDesc stopObject = {typeNull, nil};
-
- Str63 documentName;
-
- CoreTokenRecord token;
- InitCoreTokenRecord(&token);
-
- numItems = CountDocuments(GetDocumentList());
-
- switch (keyForm)
- {
- case formName: // Document by name
- {
- if (DescToPString(keyData, documentName, 63) != noErr)
- {
- error = errAECoercionFail;
- }
- else
- {
- document = GetDocumentByName(documentName);
- if (document == nil)
- error = errAENoSuchObject;
- }
- }
- break;
-
- case formAbsolutePosition: // Document by number
- error = NormalizeAbsoluteIndex(keyData, &index, numItems, &wantsAllItems);
- if ((error == noErr) && (wantsAllItems == false))
- {
- document = GetDocumentByIndex(index);
- if (document == nil)
- error = errAEIllegalIndex;
- }
- break;
-
- case formRelativePosition:
- error = ProcessFormRelativePostition(containerToken, keyData, &document);
- break;
-
- case formRange:
- switch (keyDataType)
- {
- case typeRangeDescriptor:
- error = ProcessFormRange((AEDesc *)keyData, &startObject, &stopObject);
- if (error == noErr)
- {
- DescType startType = ExtractDispatchClassFromToken(&startObject);
- DescType stopType = ExtractDispatchClassFromToken(&stopObject);
-
- if (startType != cDocument || stopType != cDocument)
- error = errAEWrongDataType;
- }
- break;
-
- default:
- error = errAEWrongDataType;
- break;
- }
- break;
-
- default:
- error = errAEEventNotHandled;
- break;
- }
-
- // if user asked for all items, and there aren't any,
- // we'll be kind and return an empty list.
-
- if (wantsAllItems && (error == errAENoSuchObject || error == errAEIllegalIndex))
- {
- error = AECreateList(NULL, 0, false, (AEDescList*)resultToken);
- goto CleanUp;
- }
-
- // fill in the result token
-
- if (error == noErr)
- {
- token.dispatchClass = cDocument;
- token.objectClass = cDocument;
- token.propertyCode = typeNull;
-
- if (wantsAllItems)
- {
- error = AECreateList(NULL, 0, false, (AEDescList*)resultToken);
-
- if (error == noErr)
- {
- for (index = 1; index <= numItems; index++)
- {
- document = GetDocumentByIndex(index);
- if (document == nil)
- goto CleanUp;
-
- token.documentNumber = GetDocumentNumber(document);
-
- error = AEPutPtr(resultToken, 0, desiredClass, &token, sizeof(token));
- if (error != noErr)
- goto CleanUp;
- }
- }
- }
- else if (keyForm == formRange)
- {
- DocumentReference beginDocument;
- DocumentReference endDocument;
- long beginIndex;
- long endIndex;
-
- error = GetDocumentReferenceFromToken(&startObject, &beginDocument);
- if (error != noErr)
- goto CleanUp;
- beginIndex = GetDocumentIndex(beginDocument);
-
- error = GetDocumentReferenceFromToken(&stopObject, &endDocument);
- if (error != noErr)
- goto CleanUp;
- endIndex = GetDocumentIndex(endDocument);
-
- error = AECreateList(NULL, 0, false, (AEDescList*)resultToken);
- if (error != noErr)
- goto CleanUp;
-
- if (beginIndex > endIndex) // swap elements
- {
- DocumentReference temp;
-
- temp = beginDocument;
- beginDocument = endDocument;
- endDocument = temp;
- }
-
- document = beginDocument;
- while (document != nil)
- {
- token.documentNumber = GetDocumentNumber(document);
-
- error = AEPutPtr(resultToken, 0, desiredClass, &token, sizeof(token));
- if (error != noErr)
- goto CleanUp;
-
- if (document == endDocument)
- break;
- document = GetNextFrontDocument(GetDocumentList(), document);
- }
- }
- else
- {
- token.documentNumber = GetDocumentNumber(document);
- error = AECreateDesc(desiredClass, &token, sizeof(token), resultToken);
- }
- }
-
- CleanUp:
-
- AEDisposeDesc(&startObject);
- AEDisposeDesc(&stopObject);
-
- return error;
- }
-
- #pragma mark -
- //----------------------------------------------------------------------------------
- // Document Property Accessor
- //----------------------------------------------------------------------------------
- // Handles properties from document token or list of document tokens
- //
- // NOTE: The container can be either a single token, or a list of tokens
- //
- //----------------------------------------------------------------------------------
-
- pascal OSErr
- PropertyFromDocumentAccessor(
- DescType desiredClass,
- const AEDesc* containerToken,
- DescType containerClass,
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken,
- long refCon)
- {
- OSErr error = noErr;
-
- if (TokenContainsTokenList((AEDescList*)containerToken) == false)
- {
- error = PropertyFromObjectAccessor(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken, refCon);
- }
- else
- {
- error = AECreateList(NULL, 0L, false, resultToken);
- if (error == noErr)
- error = PropertyFromListAccessor(desiredClass, containerToken, containerClass, keyForm, keyData, resultToken, refCon);
- }
-
- return error;
- }
-
- //----------------------------------------------------------------------------------
-
- static OSErr
- PropertyFromListAccessor(
- DescType desiredClass,
- const AEDesc* containerToken,
- DescType containerClass,
- DescType keyForm,
- const AEDesc* keyData,
- AEDesc* resultToken,
- long refCon)
- {
- OSErr error = noErr;
- long itemNum;
- long numItems;
- DescType keyword;
- AEDesc srcItem = {typeNull, nil};
- AEDesc dstItem = {typeNull, nil};
-
- error = AECountItems((AEDescList*)containerToken, &numItems);
- if (error != noErr)
- goto CleanUp;
-
- for (itemNum = 1; itemNum <= numItems; itemNum++)
- {
- error = AEGetNthDesc(containerToken, itemNum, typeWildCard, &keyword, &srcItem);
- if (error != noErr)
- goto CleanUp;
-
- if (TokenContainsTokenList(&srcItem) == false)
- {
- error = PropertyFromObjectAccessor(desiredClass, &srcItem, containerClass, keyForm, keyData, &dstItem, refCon);
- }
- else
- {
- error = AECreateList(NULL, 0L, false, &dstItem);
- if (error == noErr)
- error = PropertyFromListAccessor(desiredClass, &srcItem, containerClass, keyForm, keyData, &dstItem, refCon);
- }
-
- if (error != noErr)
- goto CleanUp;
-
- error = AEPutDesc(resultToken, itemNum, &dstItem);
- if (error != noErr)
- goto CleanUp;
-
- AEDisposeDesc(&srcItem);
- AEDisposeDesc(&dstItem);
- }
-
- CleanUp:
-
- AEDisposeDesc(&srcItem);
- AEDisposeDesc(&dstItem);
-
- return error;
- }
-
- //----------------------------------------------------------------------------------
- // Return a token representing the property for the containing window.
- // The token is returned with the property and window reference.
- //----------------------------------------------------------------------------------
-
- static OSErr
- PropertyFromObjectAccessor(
- DescType desiredType, // cProperty
- const AEDesc* containerToken,
- DescType containerClass, // cDocument
- DescType keyForm, // formPropertyID
- const AEDesc* keyData, // dataHandle points to which property
- AEDesc* resultToken, // contains our CoreTokenRecord in token.dataHandle
- long refCon )
- {
- #pragma unused (containerClass, keyForm, refCon)
-
- OSErr error;
- DescType requestedProperty;
-
- error = AEDuplicateDesc(containerToken, resultToken);
- if (error != noErr)
- return error;
-
- requestedProperty = **(DescType**)(keyData->dataHandle);
-
- if (requestedProperty == kAEAll)
- requestedProperty = pProperties;
-
- if (CanGetProperty(requestedProperty) || CanSetProperty(requestedProperty))
- {
- resultToken->descriptorType = desiredType;
- (**(CoreTokenHandle)(resultToken->dataHandle)).propertyCode = requestedProperty;
- }
- else
- {
- error = errAEEventNotHandled;
- }
-
- return error;
- }
-
- #pragma mark -
- // -------------------------------------------------------------------------------------------
- //
- // GetDataFromDocument
- //
- // Given a token that contains information about a document object, access the object
- // to extract the relevant data, and return it to the caller in the "data" parameter.
- //
- // PUBLIC: also called from the ObjectComparison callback function
- //
- // The first parameter can be a single token or a list of tokens
- // The second parameter is NULL or a list of preferred types for the return data
- //
- // -------------------------------------------------------------------------------------------
-
- OSErr
- GetDataFromDocument(AEDesc *tokenOrTokenList, AEDesc *desiredTypes, AEDesc *data)
- {
- OSErr error = noErr;
-
- if (TokenContainsTokenList(tokenOrTokenList) == false)
- {
- error = GetDataFromObject(tokenOrTokenList, desiredTypes, data);
- }
- else
- {
- error = AECreateList(NULL, 0L, false, data);
- if (error == noErr)
- error = GetDataFromList(tokenOrTokenList, desiredTypes, data);
- }
-
- return error;
- }
-
- // -------------------------------------------------------------------------------------------
- //
- // GetDataFromList
- //
- // -------------------------------------------------------------------------------------------
-
- static OSErr
- GetDataFromList(AEDesc *srcList, AEDesc *desiredTypes, AEDesc *dstList)
- {
- OSErr error = noErr;
- long itemNum;
- long numItems;
- DescType keyword;
- AEDesc srcItem = {typeNull, nil};
- AEDesc dstItem = {typeNull, nil};
-
- error = AECountItems((AEDescList*)srcList, &numItems);
- if (error != noErr)
- goto CleanUp;
-
- for (itemNum = 1; itemNum <= numItems; itemNum++)
- {
- error = AEGetNthDesc(srcList, itemNum, typeWildCard, &keyword, &srcItem);
- if (error != noErr)
- goto CleanUp;
-
- if (TokenContainsTokenList(&srcItem) == false)
- {
- error = GetDataFromObject(&srcItem, desiredTypes, &dstItem); // Get data from single item
- }
- else
- {
- error = AECreateList(NULL, 0L, false, &dstItem);
- if (error == noErr)
- error = GetDataFromList(&srcItem, desiredTypes, &dstItem);
- }
- if (error != noErr)
- goto CleanUp;
-
- error = AEPutDesc(dstList, itemNum, &dstItem);
- if (error != noErr)
- goto CleanUp;
-
- AEDisposeDesc(&srcItem);
- AEDisposeDesc(&dstItem);
- }
-
- CleanUp:
-
- AEDisposeDesc(&srcItem);
- AEDisposeDesc(&dstItem);
-
- return error;
- }
-
- //----------------------------------------------------------------------------------
- // GetDataFromObject
- //
- // Extract the document reference from a token and then return the property the user requested
- //
- //----------------------------------------------------------------------------------
-
-
- static OSErr
- GetDataFromObject(AEDesc *token, AEDesc *desiredTypes, AEDesc *data)
- {
- #pragma unused (desiredTypes)
-
- OSErr error = noErr;
- Boolean usePropertyCode = false;
- DocumentReference document = nil;
-
- DescType aType = cDocument;
- Str63 documentName;
- Boolean isModified;
-
- error = GetDocumentReferenceFromToken(token, &document);
- if (error != noErr || document == nil)
- goto CleanUp;
-
- GetDocumentName(document, documentName);
- isModified = DocumentIsModified(document);
-
- usePropertyCode = ExtractUsePropertyCodeFromToken(token);
-
- if (usePropertyCode)
- {
- DescType propertyCode = ExtractPropertyCodeFromToken(token);
-
- switch (propertyCode)
- {
- case pProperties:
- error = AECreateList(NULL, 0L, true, data);
- if (error != noErr)
- goto CleanUp;
-
- error = AEPutKeyPtr(data, pObjectType, typeType, &aType, sizeof(DescType));
- error = AEPutKeyPtr(data, pName, typeChar, &documentName[1], documentName[0]);
- error = AEPutKeyPtr(data, pIsModified, typeBoolean, &isModified, sizeof(Boolean));
- break;
-
- case pBestType:
- case pClass:
- case pDefaultType:
- case pObjectType:
- error = AECreateDesc(typeType, &aType, sizeof(DescType), data);
- break;
-
- case pName:
- error = AECreateDesc(typeChar, &documentName[1], documentName[0], data);
- break;
-
- case pIsModified:
- error = AECreateDesc(typeBoolean, &isModified, sizeof(Boolean), data);
- break;
-
- deafult:
- error = errAECantSupplyType;
- }
- }
-
- CleanUp:
-
- return error;
- }
-
- #pragma mark -
- // -------------------------------------------------------------------------------------------
- //
- // SetDataFromDocumentTokenList
- //
- // Given a token that contains a list of cWindow tokens,
- // walk the list recursively to set the data for each token in the list
- //
- // -------------------------------------------------------------------------------------------
-
- static OSErr
- SetDataForList(AEDesc *token, AEDesc *data)
- {
- OSErr error = noErr;
- AEDesc tempToken = {typeNull, nil};
-
- long numItems;
- long itemNum;
- AEKeyword keyword;
-
- if (TokenContainsTokenList(token) == false)
- {
- error = SetDataForObject(token, data);
- }
- else
- {
- error = AECountItems((AEDescList*)token, &numItems);
- if (error != noErr)
- goto CleanUp;
-
- for (itemNum = 1; itemNum <= numItems; itemNum++)
- {
- error = AEGetNthDesc((AEDescList*)token, itemNum, typeWildCard, &keyword, &tempToken);
- if (error != noErr)
- goto CleanUp;
-
- if (TokenContainsTokenList(&tempToken) == false)
- {
- error = SetDataForObject(&tempToken, data); // Set data from single item
- }
- else
- {
- error = SetDataForList(&tempToken, data); // Recurse sublist
- }
- if (error != noErr)
- goto CleanUp;
-
- AEDisposeDesc(&tempToken);
- }
- }
-
- CleanUp:
-
- AEDisposeDesc(&tempToken);
-
- return error;
- }
-
- //----------------------------------------------------------------------------------
- //
- // SetDataForObject()
- //
- //----------------------------------------------------------------------------------
- // Assumption: HandleSetData() has already filtered out all attempts
- // to write to a read-only property.
-
- // Extract the document reference from a token
- // and then store the data we received into the target property
-
- static OSErr
- SetDataForObject(AEDesc *token, AEDesc *data)
- {
-
- OSErr error = noErr;
-
- Boolean usePropertyCode;
- DescType propertyCode;
-
- DocumentReference document = nil;
-
- AEDesc propertyRecord = {typeNull, nil};
-
- usePropertyCode = ExtractUsePropertyCodeFromToken(token);
-
- error = GetDocumentReferenceFromToken(token, &document);
-
- if (usePropertyCode == false)
- {
- error = errAEWriteDenied;
- }
- else
- {
- propertyCode = ExtractPropertyCodeFromToken(token);
-
- if (data->descriptorType == typeAERecord)
- {
- error = SetProperties(document, data);
- }
- else // Build a record with one property
- {
- error = AECreateList(NULL, 0L, true, &propertyRecord);
- if (error != noErr)
- goto CleanUp;
-
- error = AEPutKeyDesc(&propertyRecord, propertyCode, data);
- if (error != noErr)
- goto CleanUp;
-
- error = SetProperties(document, &propertyRecord);
- }
- }
-
- CleanUp:
-
- AEDisposeDesc(&propertyRecord);
-
- return error;
- }
-
-
- //----------------------------------------------------------------------------------
- // SetProperties
- //----------------------------------------------------------------------------------
- // Set an object's properties from the record we receive
-
- static OSErr
- SetProperties(DocumentReference document, AEDesc *propertyRecord)
- {
- OSErr error = noErr;
- OSErr ignoreError = noErr;
-
- long numProperties = 0L;
-
- AEDesc data = {typeNull, nil};
-
- Str63 documentName;
-
- Boolean documentWasModified = false;
-
- if (propertyRecord == NULL || propertyRecord->descriptorType != typeAERecord)
- {
- error = errAEWrongDataType;
- goto CleanUp;
- }
-
- error = AECountItems(propertyRecord, &numProperties);
-
- if (error != noErr || numProperties <= 0)
- goto CleanUp;
-
- // pName
-
- ignoreError = AEGetKeyDesc(propertyRecord, pName, typeChar, &data);
- if (ignoreError != errAEDescNotFound)
- {
- error = DescToPString(&data, documentName, 63);
- if (error == noErr)
- {
- SetDocumentName(document, documentName);
- documentWasModified = true;
- }
-
- AEDisposeDesc(&data);
- }
-
- if (error == noErr && documentWasModified)
- MarkDocumentAsChanged(document);
-
- CleanUp:
-
- return error;
- }
-
- //----------------------------------------------------------------------------------
- // Token Inserter
- //----------------------------------------------------------------------------------
- // Note: token can contain the results of an AEResolve() call (ie, an object spec)
- // OR it can contain a null descriptor {typeNull, null} if insertion location
- // object was specified.
-
- static OSErr
- MakeNewObject(
- const DescType objectToCreate,
- const DescType insertionPosition,
- const AEDesc *token,
- const AEDesc *ptrToWithData,
- const AEDesc *ptrToWithProperties,
- AppleEvent *reply)
- {
- #pragma unused (objectToCreate, ptrToWithData)
-
- OSErr error = noErr;
- DocumentReference oldDocument = nil;
- DocumentReference newDocument = nil;
-
- if (token->descriptorType == typeNull)
- oldDocument = GetFrontDocument(GetDocumentList());
- else
- error = GetDocumentReferenceFromToken(token, &oldDocument);
-
- if (error == noErr)
- {
- newDocument = MakeNewDocument(NULL);
- error = DocumentError();
-
- // By default, Documents are created at the end of the list
- // If insertionPosition == kAEBeginning, then all is OK,
-
- if (error == noErr)
- {
- switch (insertionPosition)
- {
- case kAEBeginning:
- // default behavior creates element as frontmost object
- break;
-
- case kAEEnd:
- case kAEBefore:
- case kAEAfter:
- case kAEReplace:
- default:
- break;
- }
- }
-
- // Now, apply properties, if we received any properties to set,
- // then they are in a AERecord where
-
- if (ptrToWithProperties != NULL)
- {
- long numProperties = 0;
- error = AECountItems(ptrToWithProperties, &numProperties);
-
- if (error == noErr && numProperties > 0)
- {
- AEDesc propertyDesc = {typeNull, nil};
-
- // pName
-
- error = AEGetKeyDesc(ptrToWithProperties, pName, typeChar, &propertyDesc);
- if (error != errAEDescNotFound)
- {
- Str63 documentName;
- DescToPString(&propertyDesc, documentName, 63);
- SetDocumentName(newDocument, documentName);
- AEDisposeDesc(&propertyDesc);
- }
-
- if (error == errAEDescNotFound)
- error = noErr;
- }
- }
- }
-
- // return a reference to the new document in the AppleEvent reply parameter
-
- if (error == noErr && newDocument != nil)
- {
- AEDesc ospec = {typeNull, nil};
-
- error = CreateDocumentOSpec(newDocument, &ospec);
-
- if (error == noErr)
- {
- AEPutParamDesc(reply, keyDirectObject, &ospec);
- }
-
- AEDisposeDesc(&ospec);
- }
-
- CleanUp:
-
- return error;
- }
-
- #pragma mark -
- //----------------------------------------------------------------------------------
- // Application-Specific code triggered by a similarly-named HandleXXX()
- //----------------------------------------------------------------------------------
-
- static OSErr
- DoClose(AEDesc *token, const AEDesc *saving, AEDesc *savingIn)
- {
- #pragma unused (saving, savingIn)
-
- OSErr error = noErr;
- DocumentReference document;
-
- error = GetDocumentReferenceFromToken(token, &document);
-
- if (error == noErr && document != nil)
- DestroyDocument(document);
- else
- error = errAEEventNotHandled;
-
- return error;
- }
-
- //----------------------------------------------------------------------------------
- // Application-Specific code triggered by a similarly-named HandleXXX()
- //----------------------------------------------------------------------------------
-
- static OSErr
- DoSave(AEDesc *token, const AEDesc *inFile, AEDesc *asType)
- {
- #pragma unused (token, inFile, asType)
- return errAEEventNotHandled;
- }
-
-
-
- #pragma mark -
- //----------------------------------------------------------------------------------
-
- static Boolean
- CanGetProperty(DescType property)
- {
- Boolean result = false;
-
- switch (property)
- {
- // Properties we can get:
-
- case pBestType:
- case pClass:
- case pDefaultType:
- case pObjectType:
-
- case pName:
- case pProperties:
- case pIsModified:
- result = true;
- break;
-
- // Properties we can't get:
- default:
- result = false;
- break;
- }
-
- return result;
- }
-
- //----------------------------------------------------------------------------------
-
- static Boolean
- CanSetProperty(DescType property)
- {
- Boolean result = false;
-
- switch (property)
- {
- // Properties we can set:
-
- case pName:
- result = true;
- break;
-
- // Properties we can't set:
-
- default:
- case pBestType:
- case pClass:
- case pDefaultType:
- case pObjectType:
-
- case pProperties:
- case pIsModified:
- result = false;
- break;
- }
-
- return result;
- }
-
-
- #pragma mark -
-
- // -------------------------------------------------------------------------------------------
-
- static OSErr
- ProcessFormRelativePostition(const AEDesc* anchorToken, const AEDesc *keyData, DocumentReference *document)
- {
- OSErr error = noErr;
-
- DescType positionEnum;
-
- DocumentReference anchorDocument;
- DocumentReference relativeDocument = nil;
-
- *document = nil;
-
- error = GetDocumentReferenceFromToken(anchorToken, &anchorDocument);
-
- if (error == noErr)
- {
-
- switch (keyData->descriptorType)
- {
- case typeEnumerated:
- if (DescToDescType((AEDesc*)keyData, &positionEnum) != noErr)
- {
- error = errAECoercionFail;
- }
- else
- {
- switch (positionEnum)
- {
- case kAENext: // get the document behind the anchor
- *document = GetPreviousDocument(anchorDocument);
- if (*document == nil)
- error = errAENoSuchObject;
- break;
-
- case kAEPrevious: // get the document in front of the anchor
- *document = GetNextDocument(anchorDocument);
- if (*document == nil)
- error = errAENoSuchObject;
- break;
-
- default:
- error = errAEEventNotHandled;
- break;
- }
- }
- break;
-
- default:
- error = errAECoercionFail;
- break;
- }
- }
-
- return error;
- }
-
- //----------------------------------------------------------------------------------
- // Returns the index (front to back) for the specified document
- //----------------------------------------------------------------------------------
-
- static long
- GetDocumentIndex(DocumentReference document)
- {
- DocumentList list = GetDocumentList();
- DocumentReference iter = GetFrontDocument(list);
-
- Boolean foundIt = false;
- long i = 1L;
-
- while (iter != nil)
- {
- if (iter == document)
- {
- foundIt = true;
- break;
- }
-
- iter = (DocumentReference) GetNextFrontDocument(list, iter);
- i++;
- }
-
- if (!foundIt)
- i = 0;
-
- return i;
- }
-
- // -------------------------------------------------------------------------------------------
-
-